package com.shanxia.im.sdk.server.model;

import com.shanxia.codec.ProtocolDataBase;
import com.shanxia.im.sdk.server.constant.IMConstant;
import io.netty.channel.Channel;
import io.netty.util.AttributeKey;

import java.io.Serializable;
import java.net.SocketAddress;
import java.util.Objects;

/**
 * IoSession包装类,集群时 将此对象存入表中
 */
public class IMSession implements Serializable {

	private transient static final long serialVersionUID = 1L;

	public transient static String HOST = "HOST";
	public transient static final int STATE_ENABLED = 0;
	public transient static final int STATE_DISABLED = 1;

	private transient Channel session;

	/**
	 * 数据库主键ID
	 */
	private Long id;

	/**
	 * session绑定的服务器IP
	 */
	private String host;

	/**
	 * session绑定的账号
	 */
	private String account;

	private int sign;
	
	/**
	 * session在本台服务器上的ID
	 */
	private String nid; 
	
	/**
	 * 客户端ID (设备号码+应用包名),ios为deviceToken
	 */
	private String deviceId; 

	/**
	 * 终端应用版本
	 */
	private String softwareVersion;

	private int projectType;                 //充电桩项目类型
	private int startNum;                    //启动次数
	private int uploadMode;                  //数据上传模式: 1：应答模式 2：主动上报模式
	private int signInterval;                //签到间隔时间
	private int innerVariate;                //运行内部变量: 0:正常工作模式 1:IAP 模式
	private int pileNum;                     //充电枪个数
	private int heartbeatPeriod;             //心跳上报周期
	private int overtimeCount;               //心跳包检测超时次数
	private int chargingRecordCount;         //充电记录数量
	private String currentTime;              //当前充电桩系统时间
	private int randomNumber;                //桩生成随机数
	private String protocolVer;              //桩后台通信协议版本
	private int whitelistVer;                //白名单版本号
	private int deviceType;                  //设备类型: 0 充电桩 1 集中器
	
	/**
	 * 终端系统版本
	 */
	private String systemVersion; 
	
	/**
	 * 登录时间
	 */
	private Long bindTime; 
	
	/**
	 * 经度
	 */
	private Double longitude; 
	
	/**
	 * 维度
	 */
	private Double latitude; 
	
	/**
	 * 位置
	 */
	private String location; 

	/**
	 * 状态
	 */
	private int state; 


	public IMSession(Channel session) {
		this.session = session;
		this.nid = session.id().asShortText();
	}


	public IMSession() {

	}

	public void setSession(Channel session) {
		this.session = session;
	}

	public Long getId() {
		return id;
	}


	public void setId(Long id) {
		this.id = id;
	}


	public String getAccount() {
		return account;
	}

	public void setAccount(String account) {
		this.account = account;

		setAttribute(IMConstant.KEY_ACCOUNT, account);
	}

	public int getSign() {
		return sign;
	}

	public void setSign(int sign) {
		this.sign = sign;
	}

	public Double getLongitude() {
		return longitude;
	}

	public void setLongitude(Double longitude) {
		this.longitude = longitude;
	}

	public Double getLatitude() {
		return latitude;
	}

	public void setLatitude(Double latitude) {
		this.latitude = latitude;
	}

	public String getLocation() {
		return location;
	}

	public void setLocation(String location) {
		this.location = location;
	}

	public String getNid() {
		return nid;
	}

	public void setNid(String nid) {
		this.nid = nid;
	}

	public String getDeviceId() {
		return deviceId;
	}

	public void setDeviceId(String deviceId) {
		this.deviceId = deviceId;
	}

	public String getHost() {
		return host;
	}

	public Long getBindTime() {
		return bindTime;
	}

	public void setBindTime(Long bindTime) {
		this.bindTime = bindTime;
	}

	public int getProjectType() {
		return projectType;
	}

	public void setProjectType(int projectType) {
		this.projectType = projectType;
	}

	public int getStartNum() {
		return startNum;
	}

	public void setStartNum(int startNum) {
		this.startNum = startNum;
	}

	public int getUploadMode() {
		return uploadMode;
	}

	public void setUploadMode(int uploadMode) {
		this.uploadMode = uploadMode;
	}

	public int getSignInterval() {
		return signInterval;
	}

	public void setSignInterval(int signInterval) {
		this.signInterval = signInterval;
	}

	public int getInnerVariate() {
		return innerVariate;
	}

	public void setInnerVariate(int innerVariate) {
		this.innerVariate = innerVariate;
	}

	public int getPileNum() {
		return pileNum;
	}

	public void setPileNum(int pileNum) {
		this.pileNum = pileNum;
	}

	public int getHeartbeatPeriod() {
		return heartbeatPeriod;
	}

	public void setHeartbeatPeriod(int heartbeatPeriod) {
		this.heartbeatPeriod = heartbeatPeriod;
	}

	public int getOvertimeCount() {
		return overtimeCount;
	}

	public void setOvertimeCount(int overtimeCount) {
		this.overtimeCount = overtimeCount;
	}

	public int getChargingRecordCount() {
		return chargingRecordCount;
	}

	public void setChargingRecordCount(int chargingRecordCount) {
		this.chargingRecordCount = chargingRecordCount;
	}

	public String getCurrentTime() {
		return currentTime;
	}

	public void setCurrentTime(String currentTime) {
		this.currentTime = currentTime;
	}

	public int getRandomNumber() {
		return randomNumber;
	}

	public void setRandomNumber(int randomNumber) {
		this.randomNumber = randomNumber;
	}

	public String getProtocolVer() {
		return protocolVer;
	}

	public void setProtocolVer(String protocolVer) {
		this.protocolVer = protocolVer;
	}

	public int getWhitelistVer() {
		return whitelistVer;
	}

	public void setWhitelistVer(int whitelistVer) {
		this.whitelistVer = whitelistVer;
	}

	public int getDeviceType() {
		return deviceType;
	}

	public void setDeviceType(int deviceType) {
		this.deviceType = deviceType;
	}

	public String getSoftwareVersion() {
		return softwareVersion;
	}

	public void setSoftwareVersion(String softwareVersion) {
		this.softwareVersion = softwareVersion;
	}

	public String getSystemVersion() {
		return systemVersion;
	}

	public void setSystemVersion(String systemVersion) {
		this.systemVersion = systemVersion;
	}

	public void setHost(String host) {
		this.host = host;
	}

	public int getState() {
		return state;
	}

	public void setState(int state) {
		this.state = state;
	}
	
	public Channel getSession() {
		return session;
	}


	public void setAttribute(String key, Object value) {
		if (session != null) {
			session.attr(AttributeKey.valueOf(key)).set(value);
		}
	}

	public boolean containsAttribute(String key) {
		if (session != null) {
			return session.hasAttr(AttributeKey.valueOf(key));
		}
		return false;
	}

	public Object getAttribute(String key) {
		if (session != null) {
			return session.attr(AttributeKey.valueOf(key)).get();
		}
		return null;
	}

	public void removeAttribute(String key) {
		if (session != null) {
			session.attr(AttributeKey.valueOf(key)).set(null);
		}
	}

	public SocketAddress getRemoteAddress() {
		if (session != null) {
			return session.remoteAddress();
		}
		return null;
	}


	public void write(ProtocolDataBase protocolDataBase) {

		if (session == null || !session.isActive()) {
			return;
		}

		session.writeAndFlush(protocolDataBase);
	}

	public boolean isConnected() {
		return (session != null && session.isActive()) || state == STATE_ENABLED;
	}

	public void closeNow() {
		if (session != null) {
			session.close();
		}
	}

	public void closeOnFlush() {
		if (session != null) {
			session.close();
		}
	}

	@Override
	public int hashCode() {
		return getClass().hashCode();
	}

	@Override
	public boolean equals(Object o) {
		if (o instanceof IMSession) {
			IMSession target = (IMSession) o;
			return Objects.equals(target.deviceId, deviceId) && Objects.equals(target.nid, nid)
					&& Objects.equals(target.host, host);
		}
		return false;
	}

	/*public byte[] getProtobufBody() {
		SessionProto.Model.Builder builder = SessionProto.Model.newBuilder();
		if (id != null) {
			builder.setId(id);
		}
		if (account != null) {
			builder.setAccount(account);
		}
		if (nid != null) {
			builder.setNid(nid);
		}
		if (deviceId != null) {
			builder.setDeviceId(deviceId);
		}
		if (host != null) {
			builder.setHost(host);
		}
		if (channel != null) {
			builder.setChannel(channel);
		}
		if (deviceModel != null) {
			builder.setDeviceModel(deviceModel);
		}
		if (clientVersion != null) {
			builder.setClientVersion(clientVersion);
		}
		if (systemVersion != null) {
			builder.setSystemVersion(systemVersion);
		}
		if (bindTime != null) {
			builder.setBindTime(bindTime);
		}
		if (longitude != null) {
			builder.setLongitude(longitude);
		}
		if (latitude != null) {
			builder.setLatitude(latitude);
		}
		if (location != null) {
			builder.setLocation(location);
		}
		builder.setState(state);
		builder.setApns(apns);
		return builder.build().toByteArray();
	}

	
	public static IMSession decode(byte[] protobufBody) throws InvalidProtocolBufferException {
		if(protobufBody == null) {
			return null;
		}
		SessionProto.Model proto = SessionProto.Model.parseFrom(protobufBody);
		IMSession session = new IMSession();
		session.setId(proto.getId());
		session.setApns(proto.getApns());
		session.setBindTime(proto.getBindTime());
		session.setChannel(proto.getChannel());
		session.setClientVersion(proto.getClientVersion());
		session.setDeviceId(proto.getDeviceId());
		session.setDeviceModel(proto.getDeviceModel());
		session.setHost(proto.getHost());
		session.setLatitude(proto.getLatitude());
		session.setLongitude(proto.getLongitude());
		session.setLocation(proto.getLocation());
		session.setNid(proto.getNid());
		session.setSystemVersion(proto.getSystemVersion());
		session.setState(proto.getState());
		session.setAccount(proto.getAccount());
		return session;
	}*/
	

}
